package com.tgy.blog.interceptors;

import com.tgy.constant.RedisKey;
import com.tgy.exception.GlobalException;
import com.tgy.result.GraceJSONResult;
import com.tgy.util.IPUtils;
import com.tgy.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用于拦截恶意请求的
 *
 * 一分钟内一个IP访问次数大于规定次数就限制这个IP进行访问
 */
public class VisitsInterceptor implements HandlerInterceptor {

    @Autowired
    public RedisUtils redis;
    @Value("${tgy.restrictVisitsIpNumber}")
    private Integer restrictVisitsIpNumber;
    @Value("${tgy.restrictVisitsIpOut}")
    private Long restrictVisitsIpOut;
    @Value("${tgy.restrictVisitsIpTime}")
    private Long restrictVisitsIpTime;

    /**
     * 拦截请求，访问controller之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断这个IP是否已经被限制访问了
        String userIp = IPUtils.getRequestIp(request);
        userIp = userIp.replaceAll(":",".");
        boolean b = redis.keyIsExist(RedisKey.RESTRICT_VISITS_IP + ":" + userIp);
        if (b){
            GlobalException.display(GraceJSONResult.error("访问太过频繁，请"+restrictVisitsIpTime/60+"分钟后再试"));
            return false;
        }else {
            // 判断一分钟内已经访问多少次了
            boolean b1 = redis.keyIsExist(RedisKey.RESTRICT_VISITS_IP_NUMBER + ":" + userIp);
            if (b1){
                String s = redis.get(RedisKey.RESTRICT_VISITS_IP_NUMBER + ":" + userIp);
                if (Integer.valueOf(s) < restrictVisitsIpNumber){
                    redis.increment(RedisKey.RESTRICT_VISITS_IP_NUMBER + ":" + userIp,1L);
                }else {
                    // 添加进禁止访问名单
                    redis.set(RedisKey.RESTRICT_VISITS_IP + ":" + userIp,userIp,restrictVisitsIpTime);
                    return false;
                }
            }else {
                // 设置一分钟内访问次数，1分钟过期
                redis.set(RedisKey.RESTRICT_VISITS_IP_NUMBER + ":" + userIp,"1",restrictVisitsIpOut);
            }
        }
       return true;
    }

    /**
     * 请求访问到controller之后，渲染视图之前
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 请求访问到controller之后，渲染视图之后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
